package com.push.mq;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

import com.loyal.base.notify.NotifyNotification;
import com.loyal.kit.DeviceUtil;
import com.loyal.kit.OutUtil;
import com.push.mq.impl.ServerImpl;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.DisconnectedBufferOptions;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

public class MQService extends Service implements MQServerImpl {
    private MqttAndroidClient mqttAndroidClient;

    public MQService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (null == mqttAndroidClient) {
            initMqtt();
        }
        return START_STICKY;
    }

    private void initMqtt() {
        mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), mqServer(), clientId());
        mqttAndroidClient.setCallback(new MqttCallbackExtended() {
            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                if (reconnect) {
                    sendMessage("连接服务成功");
                    OutUtil.println("Reconnected to : " + serverURI);
                    // Because Clean Session is true, we need to re-subscribe
                    subscribeToTopic();
                } else {
                    OutUtil.println("Connected to: " + serverURI);
                }
            }

            @Override
            public void connectionLost(Throwable cause) {
                sendMessage("连接丢失");
                OutUtil.println("The Connection was lost.");
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                OutUtil.println("Incoming message: " + new String(message.getPayload()));
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
            }
        });
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setAutomaticReconnect(true);
        mqttConnectOptions.setCleanSession(true);
        try {
            mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
                    disconnectedBufferOptions.setBufferEnabled(true);
                    disconnectedBufferOptions.setBufferSize(100);
                    disconnectedBufferOptions.setPersistBuffer(false);
                    disconnectedBufferOptions.setDeleteOldestMessages(true);
                    mqttAndroidClient.setBufferOpts(disconnectedBufferOptions);
                    subscribeToTopic();
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    OutUtil.println("Failed to connect to: " + mqServer());
                    sendMessage("连接服务失败");
                }
            });
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private void subscribeToTopic() {
        try {
            mqttAndroidClient.subscribe(mqTopic(), 0, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    OutUtil.println("Subscribed!");
                    sendMessage("已订阅成功");
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    OutUtil.println("Failed to subscribe");
                    sendMessage("订阅主题失败");
                }
            });

            // THIS DOES NOT WORK!
            mqttAndroidClient.subscribe(mqTopic(), 0, new IMqttMessageListener() {
                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    NotifyNotification.cancel(MQService.this);
                    NotifyNotification.notify(MQService.this, new String(message.getPayload()));
                    // message Arrived!
                    OutUtil.println("Message: " + topic + " : " + new String(message.getPayload()));
                }
            });
        } catch (MqttException e) {
            OutUtil.println("Exception whilst subscribing");
            e.printStackTrace();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public String mqServer() {
        return ServerImpl.serverUri;
    }

    @Override
    public String clientId() {
        return DeviceUtil.deviceSerial();
    }

    @Override
    public String mqTopic() {
        return "examplePush";
    }

    private void sendMessage(String msg) {
        Handler handler = new Handler(getMainLooper());
        Message message = Message.obtain(handler, ServerImpl.what, msg);
        message.sendToTarget();
    }
}
